最近看了下jpa与querydsl的用法,使用起来狠舒服,几乎不用写sql。
起因
- 过去一直都使用mybatis,想要尝试一下新花样
- 都是spring全家桶的东西,据说很爽
Start
1.Jpa
- 添加jpa的依赖
build.gradle
1 | plugins { |
- 添加实体类
1 | package com.peihuan.demo; |
- 添加Repository
1 | public interface CourseRepository extends JpaRepository<Course, Long>{ |
我们的接口继承JpaRepository,泛型中,第一个是我们的实体类,第二个是主键类型。
同时,方法名必须满足一些规则,下图不完整,详情查看文档 spring-data-jpa
jpa中也提供了分页的操作,
1 | public interface CourseRepository extends JpaRepository<Course, Long> { |
到这里,jap就算结束了,在我们的service中注入CourseRepository就可以随意的调用增删改查了。
2.QueryDsl
jpa看起来很好用,为什么还需要QueryDsl呢?
因为jpa对以下场景不是特别友好:我想要查询Course,可以按title、length、teacherId查询。那么很容易写出这个接口 :
1 | Page<Course> findByTitleAndLengthAndTeacherId(String title,Long lenth,Long teacherId,Pageable pageable); |
但实际上这三个参数,可能都会有,也可能都没有,也就是传null值。但如果你真的传了null值,那么会报错,因为jpa不允许空值。
那么该肿么办呢?一种情况是把所有情况的repository接口都写出来,一共 2 * 2 * 2 种情况,在service根据参数情况,调用相应的repository接口。但如果你有五六种查询条件,很明显是不可取的了……
QueryDsl久可以解决这种情况,并可以和jpa结合使用
- 首先修改我们的依赖:
1 | plugins { |
之后会发现多了个querydsl,不用管它,直接双击运行compileJava,会自动生成一些Q开头的文件,并不需要关心其内容。
之后尝试改写Repository
1 | public interface CourseRepository extends JpaRepository<Course,Long>, QuerydslPredicateExecutor<Channel>{ |
测试后发现,这样也是错误的,参数也不能有空,那还有什么意义呢?但我们可以自己拼接BooleanExpression
1 | public interface CourseRepository extends JpaRepository<Course,Long>, QuerydslPredicateExecutor<Channel>{ |
这样就很美丽了,已经达到了我们的目标。